﻿namespace OpenComposite.Inbox.Data
{
	using System;
	using System.Collections.Generic;
	using System.Data;
	using System.ServiceModel;
	using System.Text;

	using Microsoft.Win32;

	using OpenComposite.HumanActivity.Contracts;
	using OpenComposite.Base.Collections;
	using OpenComposite.Base;
	using System.Data.SqlClient;
	using System.Diagnostics;

	public class DataAccess
	{
		#region Initialization

		public DataAccess()
		{
		}

		#endregion Initialization

		#region Public Members

		#region Constant/Read-Only Fields

		public const string cRegistryAttachmentUrl = "AttachmentSvrURL";
		public const string cRegistryDataUrl = "DataServiceURL";
		public const string cRegistryHumActFormUrl = "HumanActivityFormURL";

		#endregion Constant/Read-Only Fields

		#region Properties

		public LogInData CurrentUser
		{
			get;
			set;
		}

		public string AttachmentServiceUrl
		{
			get
			{
				return GetOption(DataAccess.cRegistryAttachmentUrl);
			}
			set
			{
				SetOption(DataAccess.cRegistryAttachmentUrl, value);
			}
		}
		public string DataServiceUrl
		{
			get
			{
				return GetOption(DataAccess.cRegistryDataUrl);
			}
			set
			{
				SetOption(DataAccess.cRegistryDataUrl, value);
			}
		}

		#endregion Properties

		#region Methods

		public LogInData LogIn(string username, string password, int orgid, int languageid, string orgname)
		{
			this.CurrentUser = this.DataService.LogIn(username, password, orgid, languageid, orgname, Helper.InboxApplicationId);
			return this.CurrentUser;
		}
		public bool LogOut()
		{
			bool ok = this.DataService.LogOut(this.CurrentUser, Helper.InboxApplicationId);
			if ( ok ) this.CurrentUser = null;
			return ok;
		}

		public BindingListEx<ActivityItem> GetActivityInbox()
		{
			if ( this.CurrentUser != null && this.CurrentUser.UserID.HasValue ) {
				return new BindingListEx<ActivityItem>(
					this.DataService.GetActivityInbox(this.CurrentUser.UserID.Value));
			} else {
				return new BindingListEx<ActivityItem>();
			}
		}
		public BindingListEx<ActivityItem> GetAdminActivityInbox(string processName, string activityName,
			DateTime createDateFrom, DateTime createDateTo, ActivityStatus[] status)
		{
			return this.DataService.GetAdminActivityInbox(processName, activityName, createDateFrom, createDateTo, status);
		}
		public List<string> GetAdminProcessNames()
		{
			return this.DataService.GetAdminProcessNames();
		}
		public List<string> GetAdminActivityNames(string process)
		{
			return this.DataService.GetAdminActivityNames(process);
		}

		public Delegation GetDelegation(string p, string p_2)
		{
			return this.DataService.GetDelegation(p, p_2);
		}
		public BindingListEx<Delegation> GetDelegations()
		{
			return new BindingListEx<Delegation>(
				this.DataService.GetDelegations(this.CurrentUser));
		}
		public void SetDelegation(Delegation delegation)
		{
			this.DataService.SetDelegation(delegation);
		}
		public bool DeleteDelegation(Delegation delegation)
		{
			return this.DataService.DeleteDelegation(delegation);
		}

		public BindingListEx<Country> GetCountries()
		{
			return new BindingListEx<Country>(this.DataService.GetCountries());
		}
		public BindingListEx<Language> GetLanguages()
		{
			return new BindingListEx<Language>(this.DataService.GetLanguages());
		}
		public BindingListEx<TimeZoneItem> GetTimeZones()
		{
			return new BindingListEx<TimeZoneItem>(this.DataService.GetTimeZones());
		}

		public UserPreferences GetUserPreferences()
		{
			return this.DataService.GetUserPreferences(this.CurrentUser);
		}
		public bool SetUserPreferences(UserPreferences userpreferences)
		{
			return this.DataService.SetUserPreferences(this.CurrentUser, userpreferences);
		}
		public PersonalUserData GetPersonalUserData()
		{
			return this.DataService.GetPersonalUserData(this.CurrentUser);
		}
		public bool SetPersonalUserData(PersonalUserData data)
		{
			return this.DataService.SetPersonalUserData(this.CurrentUser, data);
		}
		public bool UpdateUserPassword(string passwordOld, string passwordNew)
		{
			passwordOld = Helper.GetHashedString(passwordOld);
			passwordNew = Helper.GetHashedString(passwordNew);

			return this.DataService.UpdateUserPassword(this.CurrentUser, passwordOld, passwordNew);
		}

		public string GetOption(string name)
		{
			RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\OpenComposite");
			if ( rk == null ) {
				rk = Registry.CurrentUser.CreateSubKey("Software\\OpenComposite");
			}
			return rk.GetValue(name) as string;
		}
		public void SetOption(string name, string value)
		{
			RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\OpenComposite", true);
			if ( rk == null ) {
				rk = Registry.CurrentUser.CreateSubKey("Software\\OpenComposite");
			}
			rk.SetValue(name, value, RegistryValueKind.String);
		}

		public BindingListEx<AttachmentItem> GetAttachmentList(Guid workflowInstanceId)
		{
			return new BindingListEx<AttachmentItem>(
				this.AttachmentService.GetAttachmentList(this.CurrentUser, workflowInstanceId));
		}
		public byte[] GetAttachmentData(int attachmentId)
		{
			return this.AttachmentService.GetAttachmentData(this.CurrentUser, attachmentId);
		}
		public bool SetAttachment(AttachmentItem attachment)
		{
			return this.AttachmentService.SetAttachment(this.CurrentUser, attachment);
		}
		public bool DeleteAttachment(int attachmentId)
		{
			return this.AttachmentService.DeleteAttachment(this.CurrentUser, attachmentId);
		}

		public bool StopHumanActivity(int activityId, int userId, string reason, string details)
		{
			string url = this.DataService.GetHumanActivityUrl(activityId);
			if ( string.IsNullOrEmpty(url) ) return false;
			try {
				IHumanActivityFormService formService = getHumanActivityFormService(string.Format("{0}/Form", url));
				if ( formService == null ) return false;
				return formService.StopActivity(activityId, userId, reason, details);
			} catch ( Exception ex ) {
				Debug.WriteLine(ex);
				return false;
			}
		}

		public bool AbortHumanActivity(int activityId, int userId, string reason, string details)
		{
			string url = this.DataService.GetHumanActivityUrl(activityId);
			if ( string.IsNullOrEmpty(url) ) return false;
			try {
				IHumanActivityFormService formService = getHumanActivityFormService(string.Format("{0}/Form", url));
				if ( formService == null ) return false;
				return formService.AbortActivity(activityId, userId, reason, details);
			} catch ( Exception ex ) {
				Debug.WriteLine(ex);
				return false;
			}
		}
		public bool FaultHumanActivity(int activityId, int userId, string reason, string details)
		{

			string url = this.DataService.GetHumanActivityUrl(activityId);
			if ( string.IsNullOrEmpty(url) ) return false;
			try {
				IHumanActivityFormService formService = getHumanActivityFormService(string.Format("{0}/Form", url));
				if ( formService == null ) return false;
				return formService.FaultActivity(activityId, userId, reason, details);
			} catch ( Exception ex ) {
				Debug.WriteLine(ex);
				return false;
			}
		}

		public BindingListEx<OrganizationUnit> GetOrgUnits(int orgid)
		{
			return null;
		}
		#endregion Methods

		#endregion Public Members

		#region Protected Members

		#region Properties

		protected IAttachmentService AttachmentService
		{
			get
			{
				return getAttachmentService();
			}
		}

		protected IHumanActivityDataService DataService
		{
			get
			{
				return getDataService();
			}
		}

		#endregion Properties

		#endregion Protected Members

		#region Private Members

		#region Fields

		private ChannelFactory<IAttachmentService> _cfAttachment = null;
		private ChannelFactory<IHumanActivityDataService> _cfData = null;
		private ChannelFactory<IHumanActivityFormService> _cfHumanActivityForm = null;
		private IAttachmentService _attachmentSvc = null;
		private IHumanActivityDataService _dataSvc = null;
		private IHumanActivityFormService _humanActivityFormSvc = null;

		#endregion Fields

		#region Methods

		private IAttachmentService getAttachmentService()
		{
			if ( _cfAttachment == null ||
				 _cfAttachment.State == CommunicationState.Faulted ||
				 _cfAttachment.State == CommunicationState.Closing ||
				 _cfAttachment.State == CommunicationState.Closed ) {
				// create new channel factory
				_cfAttachment = new ChannelFactory<IAttachmentService>(
					new NetTcpBinding("NetTcpBinding_IAttachmentService"),
					new EndpointAddress(this.AttachmentServiceUrl));
				_attachmentSvc = null;
			}
			IClientChannel client = _attachmentSvc as IClientChannel;
			if ( _attachmentSvc == null || client == null ||
				client.State == CommunicationState.Faulted ||
				client.State == CommunicationState.Closed ||
				client.State == CommunicationState.Closing ) {
				_attachmentSvc = _cfAttachment.CreateChannel();
			}
			return _attachmentSvc;
		}

		private IHumanActivityDataService getDataService()
		{
			if ( _cfData == null ||
				 _cfData.State == CommunicationState.Faulted ||
				 _cfData.State == CommunicationState.Closing ||
				 _cfData.State == CommunicationState.Closed ) {
				// create new channel factory
				_cfData = new ChannelFactory<IHumanActivityDataService>(
					new NetTcpBinding("NetTcpBinding_IHumanActivityDataService"),
					new EndpointAddress(this.DataServiceUrl));
				_dataSvc = null;
			}
			IClientChannel client = _dataSvc as IClientChannel;
			if ( _dataSvc == null || client == null ||
				client.State == CommunicationState.Faulted ||
				client.State == CommunicationState.Closed ||
				client.State == CommunicationState.Closing ) {
				_dataSvc = _cfData.CreateChannel();
			}
			return _dataSvc;
		}

		private IHumanActivityFormService getHumanActivityFormService(string url)
		{
			// create new channel factory
			ChannelFactory<IHumanActivityFormService> channel = new ChannelFactory<IHumanActivityFormService>(
					new NetTcpBinding("NetTcpBinding_IHumanActivityFormService"),
					new EndpointAddress(url));

			return channel.CreateChannel();
		}

		#endregion Methods

		#endregion Private Members
	}
}